// 导入 Pinia 的 defineStore 方法，用于定义状态存储
import { defineStore } from "pinia"
// 导入 color 库，用于颜色转换
import Color from "color"
// 导入从 localStorage 获取数据的工具函数
import { getStorageItem } from "@/utils"
// 导入事件总线实例
import $bus from "@/bus"

// 定义并导出一个名为 useStore 的 Pinia store
const useStore = defineStore("main", {
    // state 是一个函数，返回存储的初始状态对象
    state: () => {
        return {
            // 是否为深色主题，从 localStorage 获取，默认为 false
            isDarkTheme: getStorageItem<boolean>("isDarkTheme") || false,
            // 主题色，从 localStorage 获取，默认为 "#E66740"
            primaryColor: getStorageItem<string>("primaryColor") || "#E66740",
            // 菜单是否折叠，从 localStorage 获取，默认为 false
            isCollapse: getStorageItem<boolean>("isCollapse") || false,
            // 用户信息，从 localStorage 获取，默认为空对象
            userInfo: getStorageItem<object>("userInfo") || {},
        }
    },
    // actions 对象包含可以修改状态的方法
    actions: {
        /**
         * 切换主题 明亮/黑暗
         * @param isDark 可选参数，布尔值，指定是否切换到深色主题。如果未提供，则切换当前主题状态。
         */
        changeTheme(isDark?: boolean) {
            // 如果传入了 isDark 参数，则直接设置主题
            if (typeof isDark === 'boolean') {
                this.setStorageState("isDarkTheme", isDark)
            } else {
                // 否则，切换当前的主题状态
                this.setStorageState("isDarkTheme", !this.isDarkTheme)
            }
            // 根据当前主题状态，在 HTML 根元素上添加或移除 "dark" 类
            if (this.isDarkTheme) {
                document.documentElement.classList.add("dark")
            } else {
                document.documentElement.classList.remove("dark")
            }
            // 通过事件总线发出 "themeChange" 事件，并传递当前主题状态
            $bus.emit("themeChange", this.isDarkTheme)
        },
        /**
         * 修改主题色
         * @param val 可选参数，字符串，新的主题色颜色值。如果未提供，则使用当前主题色。
         */
        changePrimaryColor(val?: string) {
            // 设置新的主题色，并将其持久化到 localStorage
            this.setStorageState("primaryColor", val || this.primaryColor)
            // 将主题色转换为 RGB 格式的字符串
            const rgb = Color(this.primaryColor).rgb().array().join(",")
            // 在 HTML 根元素上设置 CSS 变量 "--color-primary-rgb"
            document.documentElement.style.setProperty("--color-primary-rgb", rgb)
            // 通过事件总线发出 "primaryColorChange" 事件，并传递当前主题色
            $bus.emit("primaryColorChange", this.primaryColor)
        },
        /**
         * 修改菜单展开状态
         * @param val 布尔值，指定菜单是否折叠。
         */
        changeCollapse(val: boolean) {
            // 如果传入了 val 参数，则直接设置菜单折叠状态
            if (typeof val === 'boolean') {
                this.setStorageState("isCollapse", val)
            } else {
                // 否则，切换当前的菜单折叠状态 (这部分逻辑似乎有点问题，因为val是必须的boolean类型，else分支不会执行)
                // 建议修改为: this.setStorageState("isCollapse", !this.isCollapse) 如果希望点击切换
                // 或者保持现状，强制要求传入明确的布尔值
                this.setStorageState("isCollapse", !this.isCollapse)
            }
        },
        /**
         * 修改持久化数据 (localStorage 或 sessionStorage)
         * @param key 状态属性的键名
         * @param value 要设置的值
         * @param type 持久化类型，"local" (localStorage) 或 "session" (sessionStorage)，默认为 "local"
         */
        setStorageState<T extends { $state: any }>(this: T, key: keyof T['$state'], value: any, type: 'local' | 'session' = 'local') {
            // 更新 Pinia store 中的状态
            this[key] = value
            // 根据 type 参数，将数据存储到 localStorage 或 sessionStorage
            if (type === "local") {
                if (typeof value === 'object') {
                    // 如果值是对象，则转换为 JSON 字符串再存储
                    localStorage.setItem(key as string, JSON.stringify(value))
                } else {
                    localStorage.setItem(key as string, value)
                }
            }
            if (type === "session") {
                if (typeof value === 'object') {
                    // 如果值是对象，则转换为 JSON 字符串再存储
                    sessionStorage.setItem(key as string, JSON.stringify(value))
                } else {
                    sessionStorage.setItem(key as string, value)
                }
            }
        }
    }
})

// 导出 useStore，以便在其他组件中使用
export default useStore